package cc.rengu.igas.channel.cups.core.service.trans;

import cc.rengu.igas.channel.cups.common.constant.CupsConfigConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsParamConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsTreeNodeConstant;
import cc.rengu.igas.channel.cups.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.cups.core.realize.CupsMacService;
import cc.rengu.igas.channel.cups.core.realize.impl.CupsMacServiceImpl;
import cc.rengu.igas.channel.cups.core.service.base.ManageService;
import cc.rengu.igas.channel.cups.core.model.CupsFieldBean;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.KeyInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.KeyInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.KeyInfo;
import cc.rengu.oltp.service.common.entity.SecPlanInfo;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.List;
import java.util.Optional;

/**
 * 银联发起重置mac密钥
 */
public class AcpCupsResetMacKeyService extends ManageService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        return null;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        BizResponse bizResponse = new BizResponse();
        String newEncMacKey;
        int iRetCode;
        CupsFieldBean cupsFieldBean = new CupsFieldBean();
        ConvertUtil.convertOutput(cupsFieldBean);
        if (cupsFieldBean.getCupsField().getPrivAddData() != null) {
            newEncMacKey = cupsFieldBean.getCupsField().getPrivAddData().substring(4);
        } else {
            rglog.error("获取新密钥失败!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        /*获取主密钥信息*/
        KeyInfo lmkKeyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_LMK_KEY_INFO, KeyInfo.class);
        if (lmkKeyInfo == null) {
            rglog.error("获取机构主密钥失败!");
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        /*解密主密钥*/
        String macKey = descyptKey(newEncMacKey, lmkKeyInfo);
        if (macKey == null) {
            rglog.error("解密工作密钥失败!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        KeyInfo macKeyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, KeyInfo.class);
        KeyInfo macNewKeyInfo = new KeyInfo();
        if (macKeyInfo == null) {
            String algorithm = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
            String secPlanInfoStr = xmlTreeUtil.getXmlTreeStringValue(CupsTreeNodeConstant.SEC_PLAN_INFO_LIST);
            List<SecPlanInfo> secPlanInfoList = JSON.parseArray(secPlanInfoStr, SecPlanInfo.class);
            Optional<SecPlanInfo> secPlanInfoOptPin = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(CupsParamConstant.MAC_KEY_TYPE)).findFirst();
            if (secPlanInfoOptPin.isPresent()) {
                macNewKeyInfo.setKeyIndex(secPlanInfoOptPin.get().getSecPlanId() + secPlanInfoOptPin.get().getSecPlanType());
            }
            macNewKeyInfo.setAlgorithmType(algorithm);
            macNewKeyInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyyddmmHHmmss"));
            macNewKeyInfo.setKeyDesc("mac密钥");
            macNewKeyInfo.setKeyStatus("1");
            macNewKeyInfo.setKeyValue(macKey);
        } else {
            BeanUtil.beanCopy(macKeyInfo, macNewKeyInfo);
            macNewKeyInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyyddmmHHmmss"));
            macNewKeyInfo.setKeyValue(macKey);
        }
        /*用新密钥验证mac*/
        String macBlock = xmlTreeUtil.getXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MAC_BLOCK);
        CupsMacService cupsMacService = new CupsMacServiceImpl();
        if (!cupsMacService.verifyReSetKeyMacString(macNewKeyInfo, cupsFieldBean.getCupsField().getMac(), macBlock)) {
            rglog.error("新密钥验证mac错误!");
            if (macKeyInfo != null) {
                /*用旧的密钥验证一遍*/
                if (!cupsMacService.verifyMacString(macKeyInfo, cupsFieldBean.getCupsField().getMac(), macBlock)) {
                    rglog.error("旧密钥验证mac错误!");
                    throw new BizException(RespCodeEnum.VERIFY_MAC_ERROR.getRespCode(), RespCodeEnum.VERIFY_MAC_ERROR.getRespDesc());
                }
            } else {
                throw new BizException(RespCodeEnum.VERIFY_MAC_ERROR.getRespCode(), RespCodeEnum.VERIFY_MAC_ERROR.getRespDesc());
            }
        }
        /*更新mac密钥*/
        KeyInfoMapper keyInfoMapper = new KeyInfoMapperImpl();
        if (macKeyInfo == null) {
            /*插入密钥*/
            iRetCode = keyInfoMapper.insertKeyInfo(macNewKeyInfo);
        } else {
            iRetCode = keyInfoMapper.updateKeyInfoByPrimaryKey(macNewKeyInfo);
        }
        if (iRetCode != 0) {
            rglog.error("更新macKey失败,iRetCode=[{}]", iRetCode);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        xmlTreeUtil.setXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, macNewKeyInfo);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {

    }

    String descyptKey(String encKey, KeyInfo keyInfo) throws Exception {
        byte[] encData = ByteUtil.hexStringToByte(encKey);
        String encType = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ENC_TYPE);
        if ("0".equals(encType)) {
            rglog.debug("使用软加密,算法类型:<{}>,", keyInfo.getAlgorithmType());
            if ("3DES".equals(keyInfo.getAlgorithmType())) {
                /* return ByteUtil.bytesToHexString(DES3Util.decryptMode3DESDouble(ByteUtil.hexStringToByte(keyInfo.getKeyValue()),encData));*/
                return null;
            } else {
                byte[] keyValue = new byte[16];
                byte[] lmkKey = ByteUtil.hexStringToByte(keyInfo.getKeyValue());
                int iRet = SM4Util.sms4(encData, encData.length, lmkKey, keyValue, 0);
                if (iRet == 0) {
                    return ByteUtil.bytesToHexString(keyValue);
                } else {
                    return null;
                }
            }
        } else {
            /*硬加密，需要自己客户化*/
            return null;
        }
    }

}
